package com.example.jobback.service.manager.impl;

import com.alibaba.fastjson.JSON;
import com.example.jobback.common.enums.ManagerType;
import com.example.jobback.config.AuthConfig;
import com.example.jobback.mapper.ManagerMapper;
import com.example.jobback.po.Manager;
import com.example.jobback.po.User;
import com.example.jobback.req.common.page.PageReq;
import com.example.jobback.req.manager.employee.ManagerEmployeeCreatedReq;
import com.example.jobback.resp.manager.employee.page.manager.GetPageManagerResp;
import com.example.jobback.resp.manager.employee.page.manager.GetPageManagersResp;
import com.example.jobback.resp.manager.employee.page.recruiter.MCrossGetPageRecruiterResp;
import com.example.jobback.resp.manager.employee.page.recruiter.MCrossGetPageRecruitersResp;
import com.example.jobback.resp.manager.employee.page.seeker.MCrossGetPageSeekerResp;
import com.example.jobback.resp.manager.employee.page.seeker.MCrossGetPageSeekersResp;
import com.example.jobback.resp.recruiter.common.page.RCrossGetPageRecruiterResp;
import com.example.jobback.resp.recruiter.common.page.RCrossGetPageRecruitersResp;
import com.example.jobback.resp.recruiter.company.page.RCrossGetPageCompanyListResp;
import com.example.jobback.resp.seeker.common.page.SCrossGetPageSeekerResp;
import com.example.jobback.resp.seeker.common.page.SCrossGetPageSeekersResp;
import com.example.jobback.result.Result;
import com.example.jobback.service.common.UserCommonService;
import com.example.jobback.service.manager.ManagerEmployeeService;
import com.example.jobback.util.*;
import com.example.jobback.websocket.service.MessageService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.example.jobback.util.RedisConstants.*;
import static java.time.LocalDateTime.now;

/**
 * @ClassName: ManagerEmployeeServiceImpl
 * @Description:管理员-员工管理服务接口实现类
 * @Author: lhb
 * @Date: 2025/6/30
 */
@Service
public class ManagerEmployeeServiceImpl implements ManagerEmployeeService {
    private final UserCommonService userCommonService;


    @Value("${cross_service_baseurl}")
    private String crossServiceBaseUrl;

    private final PhoneNumberUtils phoneNumberUtils;

    private final RestTemplate restTemplate;

    private final CACHEUtil cacheUtil;

    private final MessageService messageService;

    private final ManagerMapper managerMapper;

    private final AuthConfig authConfig;

    public ManagerEmployeeServiceImpl(UserCommonService userCommonService, AuthConfig authConfig, ManagerMapper managerMapper, PhoneNumberUtils phoneNumberUtils, RestTemplate restTemplate, CACHEUtil cacheUtil, MessageService messageService) {
        this.userCommonService = userCommonService;
        this.authConfig = authConfig;
        this.managerMapper = managerMapper;
        this.phoneNumberUtils = phoneNumberUtils;
        this.restTemplate = restTemplate;
        this.cacheUtil = cacheUtil;
        this.messageService = messageService;
    }


    /**
     * @Description: 增设员工
     * @param req 
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/30 14:32
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> createEmployee(ManagerEmployeeCreatedReq req) {
        Manager manager = TLUtil.get(TLUtil.M);
        if(!manager.getManagerType().equals(ManagerType.SUPER)){
            throw new IllegalArgumentException("VALIDATION_ERROR：无权限");
        }
        String phone = req.getPhone();
        String password=req.getPassword();
        ManagerType type=req.getType();
        String phoneAes= null;
        String passwordAes=null;
        //加密电话号码
        try {
            phoneAes = SecureEncryptionUtil.encrypt(phone,authConfig.getPhoneSecret());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        User user = userCommonService.getUserByPhoneAes(phoneAes);
        //注册过
        if(Objects.equals(req.getEmployeeCreatedSelect(), 0)) {
            if(Objects.isNull(user)) {
                throw new IllegalArgumentException("VALIDATION_ERROR：该账号无记录");
            }
        } else {
            //新注册
            if(Objects.nonNull(user)) {
                throw new IllegalArgumentException("VALIDATION_ERROR：该账号已有记录");
            }
            //注册
            user = userCommonService.registerUser(phoneAes);
            //加密密码
            try {
                passwordAes = SecureEncryptionUtil.encrypt(password,authConfig.getPasswordSecret());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            if(userCommonService.registerUserAuth(user.getUserId(),passwordAes)==0) {
                throw new RuntimeException("注册失败");
            }
        }
        //判断是否已经是管理员
        Manager checkManager = managerMapper.getManagerByUserId(user.getUserId());
        if(Objects.nonNull(checkManager)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：该用户已经是管理员");
        }
        //插入到管理员表
        Manager registerManager=new Manager();
        BeanUtils.copyProperties(user,registerManager);
        registerManager.setManagerType(type);
        registerManager.setCreatedAt(now());
        registerManager.setUpdatedAt(now());
        if(managerMapper.register(registerManager) == 0) {
            throw new RuntimeException("注册失败");
        }
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),
                MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL, TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        return Result.success(token);
    }

    /**
     * @Description: 删除管理员
     * @param deleteUserId 
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/30 15:42
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> deleteManager(Long deleteUserId) {
        Manager manager = TLUtil.get(TLUtil.M);
        if(!manager.getManagerType().equals(ManagerType.SUPER)){
            throw new IllegalArgumentException("VALIDATION_ERROR：无权限");
        }
        Manager deleteManager = managerMapper.getManagerByUserId(deleteUserId);
        if(deleteManager==null)  {
            throw new IllegalArgumentException("VALIDATION_ERROR：用户不存在或者用户非管理员身份");
        }
        if(deleteManager.getManagerType().equals(ManagerType.SUPER)){
            throw new IllegalArgumentException("VALIDATION_ERROR：无权限super用");
        }
        if(managerMapper.deleteManager(deleteUserId)==0){
            throw new RuntimeException("删除失败");
        }
        //删除聊天记录，并且关闭websocket连接
        messageService.clearUserMessageRecord(deleteUserId, messageService.managerRole);
        //删除登录态
        cacheUtil.deleteKeySafely(MANAGER_KEY+deleteUserId);
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),
                MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL, TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        return Result.success(token);
    }

    /**
     * @Description: 分页查询（含搜索内容）查找manager列表
     * @param pageNum
     * @param pageSize
     * @param content 
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/7/1 9:48
     */
    @Override
    public Result<GetPageManagersResp> getManagers(int pageNum, int pageSize, String content) {
        if(content.isEmpty()){
            PageHelper.startPage(pageNum, pageSize);
            List<Manager> managers = managerMapper.getManagers();
            //获取页的相关信息
            PageInfo<Manager> managerPageInfo = new PageInfo<>(managers);
            //获取userid查找user对象
            List<Long> userIds = managers.stream()
                    .map(Manager::getUserId)
                    .filter(Objects::nonNull)
                    .toList();
            List<User> users=userCommonService.getUsersByUserIds(userIds);
            //处理分页查询管理员列表响应体
            GetPageManagersResp resp = processPageManagerList(managers, users,managerPageInfo);
            return Result.success(resp);
        }
        List<User> users=userCommonService.getUsersByName(content);
        if(users.isEmpty()){
            GetPageManagersResp resp = new GetPageManagersResp();
            resp.setPages(0);
            resp.setTotal(0L);
            resp.setPageNum(0);
            resp.setPageSize(0);
            resp.setSize(0);
            resp.setRespList(new ArrayList<>());
            return Result.success(resp);
        }
        List<Long> userIds = users.stream()
                .map(User::getUserId)
                .filter(Objects::nonNull)
                .toList();
        PageHelper.startPage(pageNum, pageSize);
        List<Manager> managers = managerMapper.getManagersByUserIds(userIds);
        //获取页的相关信息
        PageInfo<Manager> managerPageInfo = new PageInfo<>(managers);
        //处理分页查询管理员列表响应体
        GetPageManagersResp resp = processPageManagerList(managers, users,managerPageInfo);
        return Result.success(resp);
    }

    /**
     * @Description: 分页查询（含搜索内容）查找seekers列表，跨服务调用
     * @param page
     * @param size
     * @param content
     * @return Result<MCrossGetPageSeekersResp>
     * @Author lhb
     * @CreateTime 2025/7/3 15:55
     */
    @Override
    public Result<MCrossGetPageSeekersResp> getSeekers(int page, int size, String content) {
        Manager manager=TLUtil.get(TLUtil.M);
        Long userId=manager.getUserId();
        //跨服务调用
        PageReq pageReq=new PageReq();
        pageReq.setSize(size);
        pageReq.setContent(content);
        pageReq.setPage(page);
        String url = crossServiceBaseUrl + "/seeker/common/getSeekers";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<Object> result = null;
        try {
            result = invoker.invokeAndHandle(
                    url,
                    HttpMethod.POST,
                    pageReq,
                    Object.class,
                    userId,
                    null
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!result.getCode().equals(HttpServletResponse.SC_CREATED)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：查询失败");
        }
        SCrossGetPageSeekersResp sCrossGetPageSeekersResp =
                JSON.parseObject(JSON.toJSONString(result.getData()),
                SCrossGetPageSeekersResp.class);
        //初始化响应体
        MCrossGetPageSeekersResp resp=new MCrossGetPageSeekersResp();
        resp.setRespList(new ArrayList<>());
        //因为BeanUtils的权限，使用循环构造
        BeanUtils.copyProperties(sCrossGetPageSeekersResp, resp);
        for (SCrossGetPageSeekerResp sCrossGetPageSeekerResp:sCrossGetPageSeekersResp.getRespList()){
            MCrossGetPageSeekerResp mCrossGetPageSeekerResp=new MCrossGetPageSeekerResp();
            BeanUtils.copyProperties(sCrossGetPageSeekerResp, mCrossGetPageSeekerResp);
            resp.getRespList().add(mCrossGetPageSeekerResp);
        }
        return Result.success(resp);
    }

    /**
     * @Description: 分页跨服务调用recruiter列表，调用方
     * @param page
     * @param size
     * @param content
     * @return Result<MCrossGetPageRecruitersResp>
     * @Author lhb
     * @CreateTime 2025/7/3 17:30
     */
    @Override
    public Result<MCrossGetPageRecruitersResp> getRecruiters(int page, int size, String content) {
        Manager manager=TLUtil.get(TLUtil.M);
        Long userId=manager.getUserId();
        //跨服务调用
        PageReq pageReq=new PageReq();
        pageReq.setPage(page);
        pageReq.setSize(size);
        pageReq.setContent(content);
        String url = crossServiceBaseUrl + "/recruiter/common/getRecruiters";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<Object> result = null;
        try {
            result = invoker.invokeAndHandle(
                    url,
                    HttpMethod.POST,
                    pageReq,
                    Object.class,
                    userId,
                    null
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        if(!result.getCode().equals(HttpServletResponse.SC_CREATED)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：查询失败");
        }
        RCrossGetPageRecruitersResp rCrossGetPageRecruitersResp =
                JSON.parseObject(JSON.toJSONString(result.getData()),
                RCrossGetPageRecruitersResp.class);

        //初始化响应体
        MCrossGetPageRecruitersResp resp=new MCrossGetPageRecruitersResp();
        resp.setRespList(new ArrayList<>());
        //因为BeanUtils的权限，使用循环构造
        BeanUtils.copyProperties(rCrossGetPageRecruitersResp, resp);
        for (RCrossGetPageRecruiterResp rCrossGetPageRecruiterResp:rCrossGetPageRecruitersResp.getRespList()){
            MCrossGetPageRecruiterResp mCrossGetPageRecruiterResp=new MCrossGetPageRecruiterResp();
            BeanUtils.copyProperties(rCrossGetPageRecruiterResp, mCrossGetPageRecruiterResp);
            resp.getRespList().add(mCrossGetPageRecruiterResp);
        }
        return Result.success(resp);
    }

    /**
     * @Description:  使用stream.map等处理分页查询管理员列表响应体
     * @return GetPageManagersResp
     * @Author lhb
     * @CreateTime 2025/7/1 11:03
     */
    private GetPageManagersResp processPageManagerList(List<Manager> managers,List<User> users,
                                                       PageInfo<Manager> managerPageInfo) {
        //初始化响应体
        GetPageManagersResp resp=new GetPageManagersResp();
        resp.setRespList(new ArrayList<>());
        // 使用 Stream 和 map 方法进行映射
        List<Manager> mappedManagers = managers.stream()
                .map(manager -> {
                    // 找到对应的 User
                    users.stream()
                            .filter(u -> u.getUserId().equals(manager.getUserId()))
                            .findFirst().ifPresent(user -> BeanUtils.copyProperties(user, manager));
                    return manager;
                })
                .toList();
        resp.setPages(managerPageInfo.getPages());
        resp.setTotal(managerPageInfo.getTotal());
        resp.setPageNum(managerPageInfo.getPageNum());
        resp.setPageSize(managerPageInfo.getPageSize());
        resp.setSize(managerPageInfo.getSize());
        List<Manager> pageManagerList=managerPageInfo.getList();
        for (Manager manager:pageManagerList){
            String phone="";
            try {
                phone=phoneNumberUtils.decryptPhone(manager.getPhoneAes());
            } catch (Exception e) {
                throw new RuntimeException("电话号码格式有误，解密失败");
            }
            GetPageManagerResp managerResp=new GetPageManagerResp();
            BeanUtils.copyProperties(manager,managerResp);
            managerResp.setPhone(phone);
            resp.getRespList().add(managerResp);
        }
        return resp;
    }
}
